﻿using System;
using System.IO;
using System.Text;

namespace SanlieHash.Fast
{
    using SanlieHash.Encoder;
    using SanlieHash.Morse;

    public class FastEncode
    {
        internal static Morse morse = new Morse();
        public static byte[] EncodeMorse(string msg)
        {
            return morse.Encode(msg, msg.Length);
        }
        public static string DecodeMorse(byte[] morse_bytes)
        {
            return morse.Decode(morse_bytes, morse_bytes.Length);
        }
        public static string EncodeUInt(uint num)
        {
            return EncodeHex(Helper.uint2byte(num));
        }
        public static uint DecodeUInt(string uint_text)
        {
            return Helper.byte2uint(DecodeHex(uint_text), 0);
        }
        public static string EncodeHex(byte[] data)
        {
            return Helper.ToHexString(data);
        }
        public static byte[] DecodeHex(string hexString)
        {
            return Helper.ToBytes(hexString);
        }
        public static string Base64Encode(byte[] data)
        {
            var output = string.Empty;
            var base64 = new Base64();

            int len;
            for (int i = 0; i < data.Length; i += base64.EncodeMaxLength)
            {
                len = base64.Encode(data, i, base64.EncodeMaxLength);
                if (len > 0) output += Encoding.ASCII.GetString(base64.Buffer, 0, len);
            }
            return output;
        }
        public static string Base64Encode(string text, Encoding encoding = null)
        {
            if (encoding==null) encoding = Encoding.UTF8;
            var output = string.Empty;
            var base64 = new Base64();
            var data = encoding.GetBytes(text);

            int len;
            for (int i = 0; i < data.Length; i += base64.EncodeMaxLength)
            {
                len = base64.Encode(data, i, base64.EncodeMaxLength);
                if (len > 0) output += Encoding.ASCII.GetString(base64.Buffer, 0, len);
            }
            return output;
        }
        public static string Base64Decode(string base64text, Encoding encoding = null)
        {
            if (encoding==null) encoding = Encoding.UTF8;
            var output = string.Empty;
            var base64 = new Base64();

            var data = Encoding.ASCII.GetBytes(base64text);
            int len;
            for (int i = 0; i < data.Length; i += base64.DecodeMaxLength)
            {
                len = base64.Decode(data, i, base64.DecodeMaxLength);
                if (len > 0) output += encoding.GetString(base64.Buffer, 0, len);
            }
            return output;
        }
        public static byte[] Base64Decode2Bytes(string base64text)
        {
            using (var output = new MemoryStream())
            {
                var base64 = new Base64();

                var data = Encoding.ASCII.GetBytes(base64text);
                int len;
                for (int i = 0; i < data.Length; i += base64.DecodeMaxLength)
                {
                    len = base64.Decode(data, i, base64.DecodeMaxLength);
                    if (len > 0) output.Write(base64.Buffer, 0, len);
                }
                return output.ToArray();
            }
        }
        public static void Base64EncodeStream(Stream source, Stream dist)
        {
            var base64 = new Base64();
            var buf = new byte[base64.EncodeMaxLength];
            int readed;
            int readed_64;
            source.Seek(0, SeekOrigin.Begin);
            dist.SetLength(0);
            dist.Seek(0, SeekOrigin.Begin);
            dist.Flush();
            while (source.Position < source.Length)
            {
                readed = source.Read(buf, 0, buf.Length);
                if (readed > 0)
                {
                    readed_64 = base64.Encode(buf, 0, readed);
                    if (readed_64 > 0) dist.Write(base64.Buffer, 0, readed_64);
                }
                else break;
            }
            dist.Flush();
        }
        public static void Base64DecodeStream(Stream source, Stream dist)
        {
            var base64 = new Base64();
            var buf = new byte[base64.DecodeMaxLength];
            int readed;
            int readed_64;
            source.Seek(0, SeekOrigin.Begin);
            dist.SetLength(0);
            dist.Seek(0, SeekOrigin.Begin);
            dist.Flush();
            while (source.Position < source.Length)
            {
                readed = source.Read(buf, 0, buf.Length);
                if (readed > 0)
                {
                    readed_64 = base64.Decode(buf, 0, readed);
                    if (readed_64 > 0) dist.Write(base64.Buffer, 0, readed_64);
                }
                else break;
            }
            dist.Flush();
        }
    }
}
